package com.dacd.sdl.sendclient.service;

import android.app.Service;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.IBinder;
import android.util.Log;

import com.dacd.sdl.sendclient.EventBean.NoticeEvent;
import com.dacd.sdl.sendclient.EventBean.StopEvent;
import com.dacd.sdl.sendclient.EventBean.UnlockEvent;
import com.dacd.sdl.sendclient.EventBean.UploadEvent;
import com.dacd.sdl.sendclient.R;
import com.dacd.sdl.sendclient.activity.LockScreenActivity;
import com.smartdevicelink.exception.SdlException;
import com.smartdevicelink.proxy.RPCRequest;
import com.smartdevicelink.proxy.RPCResponse;
import com.smartdevicelink.proxy.SdlProxyALM;
import com.smartdevicelink.proxy.callbacks.OnServiceEnded;
import com.smartdevicelink.proxy.callbacks.OnServiceNACKed;
import com.smartdevicelink.proxy.interfaces.IProxyListenerALM;
import com.smartdevicelink.proxy.rpc.AddCommandResponse;
import com.smartdevicelink.proxy.rpc.AddSubMenuResponse;
import com.smartdevicelink.proxy.rpc.AlertManeuverResponse;
import com.smartdevicelink.proxy.rpc.AlertResponse;
import com.smartdevicelink.proxy.rpc.ButtonPressResponse;
import com.smartdevicelink.proxy.rpc.ChangeRegistrationResponse;
import com.smartdevicelink.proxy.rpc.CreateInteractionChoiceSetResponse;
import com.smartdevicelink.proxy.rpc.DeleteCommandResponse;
import com.smartdevicelink.proxy.rpc.DeleteFileResponse;
import com.smartdevicelink.proxy.rpc.DeleteInteractionChoiceSetResponse;
import com.smartdevicelink.proxy.rpc.DeleteSubMenuResponse;
import com.smartdevicelink.proxy.rpc.DiagnosticMessageResponse;
import com.smartdevicelink.proxy.rpc.DialNumberResponse;
import com.smartdevicelink.proxy.rpc.EndAudioPassThruResponse;
import com.smartdevicelink.proxy.rpc.GenericResponse;
import com.smartdevicelink.proxy.rpc.GetDTCsResponse;
import com.smartdevicelink.proxy.rpc.GetInteriorVehicleDataResponse;
import com.smartdevicelink.proxy.rpc.GetSystemCapabilityResponse;
import com.smartdevicelink.proxy.rpc.GetVehicleDataResponse;
import com.smartdevicelink.proxy.rpc.GetWayPointsResponse;
import com.smartdevicelink.proxy.rpc.Image;
import com.smartdevicelink.proxy.rpc.ListFiles;
import com.smartdevicelink.proxy.rpc.ListFilesResponse;
import com.smartdevicelink.proxy.rpc.OnAudioPassThru;
import com.smartdevicelink.proxy.rpc.OnButtonEvent;
import com.smartdevicelink.proxy.rpc.OnButtonPress;
import com.smartdevicelink.proxy.rpc.OnCommand;
import com.smartdevicelink.proxy.rpc.OnDriverDistraction;
import com.smartdevicelink.proxy.rpc.OnHMIStatus;
import com.smartdevicelink.proxy.rpc.OnHashChange;
import com.smartdevicelink.proxy.rpc.OnInteriorVehicleData;
import com.smartdevicelink.proxy.rpc.OnKeyboardInput;
import com.smartdevicelink.proxy.rpc.OnLanguageChange;
import com.smartdevicelink.proxy.rpc.OnLockScreenStatus;
import com.smartdevicelink.proxy.rpc.OnPermissionsChange;
import com.smartdevicelink.proxy.rpc.OnStreamRPC;
import com.smartdevicelink.proxy.rpc.OnSystemRequest;
import com.smartdevicelink.proxy.rpc.OnTBTClientState;
import com.smartdevicelink.proxy.rpc.OnTouchEvent;
import com.smartdevicelink.proxy.rpc.OnVehicleData;
import com.smartdevicelink.proxy.rpc.OnWayPointChange;
import com.smartdevicelink.proxy.rpc.PerformAudioPassThruResponse;
import com.smartdevicelink.proxy.rpc.PerformInteractionResponse;
import com.smartdevicelink.proxy.rpc.PutFile;
import com.smartdevicelink.proxy.rpc.PutFileResponse;
import com.smartdevicelink.proxy.rpc.ReadDIDResponse;
import com.smartdevicelink.proxy.rpc.ResetGlobalPropertiesResponse;
import com.smartdevicelink.proxy.rpc.ScrollableMessageResponse;
import com.smartdevicelink.proxy.rpc.SendHapticDataResponse;
import com.smartdevicelink.proxy.rpc.SendLocationResponse;
import com.smartdevicelink.proxy.rpc.SetAppIconResponse;
import com.smartdevicelink.proxy.rpc.SetDisplayLayout;
import com.smartdevicelink.proxy.rpc.SetDisplayLayoutResponse;
import com.smartdevicelink.proxy.rpc.SetGlobalPropertiesResponse;
import com.smartdevicelink.proxy.rpc.SetInteriorVehicleDataResponse;
import com.smartdevicelink.proxy.rpc.SetMediaClockTimerResponse;
import com.smartdevicelink.proxy.rpc.Show;
import com.smartdevicelink.proxy.rpc.ShowConstantTbtResponse;
import com.smartdevicelink.proxy.rpc.ShowResponse;
import com.smartdevicelink.proxy.rpc.SliderResponse;
import com.smartdevicelink.proxy.rpc.SpeakResponse;
import com.smartdevicelink.proxy.rpc.StreamRPCResponse;
import com.smartdevicelink.proxy.rpc.SubscribeButtonResponse;
import com.smartdevicelink.proxy.rpc.SubscribeVehicleDataResponse;
import com.smartdevicelink.proxy.rpc.SubscribeWayPointsResponse;
import com.smartdevicelink.proxy.rpc.SystemRequestResponse;
import com.smartdevicelink.proxy.rpc.UnsubscribeButtonResponse;
import com.smartdevicelink.proxy.rpc.UnsubscribeVehicleDataResponse;
import com.smartdevicelink.proxy.rpc.UnsubscribeWayPointsResponse;
import com.smartdevicelink.proxy.rpc.UpdateTurnListResponse;
import com.smartdevicelink.proxy.rpc.enums.FileType;
import com.smartdevicelink.proxy.rpc.enums.HMILevel;
import com.smartdevicelink.proxy.rpc.enums.ImageType;
import com.smartdevicelink.proxy.rpc.enums.SdlDisconnectedReason;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCResponseListener;
import com.smartdevicelink.transport.BaseTransportConfig;
import com.smartdevicelink.transport.TCPTransportConfig;
import com.smartdevicelink.util.CorrelationIdGenerator;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 核心service，用来控制sdl的生命周期。
 * 创建连接SDL
 * 在连接之后接收和发送信息
 */
public class SdlService extends Service implements IProxyListenerALM {

    private static final String TAG = "SDL Service";
    private static final int TCP_PORT = 12345;//local test
    //    private static final int TCP_PORT                   = 5109;//official manticore test
    private static final String APP_NAME = "DACD SDL";
    private static final String APP_ID = "667";
    private static final String ICON_FILENAME = "dacd_sdl_icon.png";//服务器封面图标
    private static final String LOCK_IMG_FILENAME = "dacd_lock_img.png";//服务器接收的锁屏上传图片
    //用于处理SDL与app之间的通信
    private SdlProxyALM proxy = null;
    private List<String> remoteFiles;//远程服务器连接图标
    private int iconCorrelationId;//远程服务器图标ID
    private int lockImgId;//锁屏图片的ID
    private boolean isLockShow;

    @Override
    public void onCreate() {
        super.onCreate();
        remoteFiles = new ArrayList<>();//初始化远程服务器连接图标
        isLockShow = false;
        if (!EventBus.getDefault().isRegistered(this)) {//注册事件通知
            EventBus.getDefault().register(this);
        }
    }

    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        new Thread() {
            @Override
            public void run() {
                super.run();
                startProxy(intent);
            }
        }.start();
        return START_STICKY;
    }

    /**
     * 开始创建代理连接
     *
     * @param intent
     */
    private void startProxy(Intent intent) {
        if (proxy == null) {//代理不存在的时候才重新创建，存在的话不做任何动作
            BaseTransportConfig transport = null;//初始化为空，为以后拓展多种连接方式做好准备
            transport = new TCPTransportConfig(TCP_PORT, initIpAddress(intent), true);
            try {
                proxy = new SdlProxyALM(this, APP_NAME, true, APP_ID, transport);
            } catch (SdlException e) {
                e.printStackTrace();
                if (proxy == null) {
                    stopSelf();
                }
            }
        } else {
            //TODO 提示存在连接，之前的连接没有断开
            NoticeEvent noticeEvent = new NoticeEvent();
            noticeEvent.setNoticeContent("之前的连接没有断开");
            EventBus.getDefault().post(noticeEvent);
        }
    }

    /**
     * 使用TCP连接的时候，初始化IP ADDRESS
     */
    private String initIpAddress(Intent intent) {
        String defaultIpAddress = "192.168.1.4";//for local test
//        String defaultIpAddress = "m.sdl.tools";//official Manticore test
        if (intent != null) {
            String inputIpAddress = intent.getStringExtra("ipAddress");
            if (inputIpAddress != null && !inputIpAddress.equals("")) {
                defaultIpAddress = inputIpAddress;
            }
        }
        return defaultIpAddress;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * 重载回调显示了连接的状态
     * NONE的时候，代表解锁屏幕等待服务器点击图标的状态
     * FULL的时候代表服务器点击图标。可以开始进行信息传递
     * LIMITED代表连接过，处于服务器列表待点击状态
     *
     * @param notification
     */
    @Override
    public void onOnHMIStatus(OnHMIStatus notification) {
        //TODO
        Log.e(TAG, "onOnHMIStatus: " + notification.getHmiLevel());
        if (notification.getHmiLevel().equals(HMILevel.HMI_NONE)) {//如果是NONE连接状态
            if (notification.getFirstRun()) {//如果是第一次就上传图标
                NoticeEvent noticeEvent = new NoticeEvent();
                noticeEvent.setNoticeContent("已连接");
                EventBus.getDefault().post(noticeEvent);
                uploadImages();
            }
            bigImageLayoutRequest();//申请大图显示布局


        } else if (notification.getHmiLevel().equals(HMILevel.HMI_FULL)) {//进入主屏开始锁屏
            startLockActivity();
        } else if (notification.getHmiLevel().equals(HMILevel.HMI_LIMITED)) {//离开主屏停止锁屏
            unLockScreen();
        }
    }

    /**
     * 申请大图布局
     */
    private void bigImageLayoutRequest() {
        SetDisplayLayout setDisplayLayoutRequest = new SetDisplayLayout();
        setDisplayLayoutRequest.setDisplayLayout("LARGE_GRAPHIC_ONLY");
        setDisplayLayoutRequest.setOnRPCResponseListener(new OnRPCResponseListener() {
            @Override
            public void onResponse(int correlationId, RPCResponse response) {
                if (((SetDisplayLayoutResponse) response).getSuccess()) {
                    Log.i("SdlService", "Display layout set successfully.");
                    // Proceed with more user interface RPCs
                } else {
                    Log.i("SdlService", "Display layout request rejected.");
                }
            }
        });
        try {
            proxy.sendRPCRequest(setDisplayLayoutRequest);
        } catch (SdlException e) {
            e.printStackTrace();
        }
    }

    /**
     * 启动锁屏
     */
    private void startLockActivity() {
        if (!isLockShow) {
            isLockShow = true;
            Intent intent = new Intent(this, LockScreenActivity.class);
            startActivity(intent);
        }
    }

    /**
     * 解除锁屏的通知
     */
    private void unLockScreen() {
        EventBus.getDefault().post(new UnlockEvent());
        isLockShow = false;
    }

    /**
     * 请求图标列表，上传缺失图标
     */
    private void uploadImages() {
        ListFiles listFiles = new ListFiles();
        listFiles.setOnRPCResponseListener(new OnRPCResponseListener() {
            @Override
            public void onResponse(int correlationId, RPCResponse response) {
                if (response.getSuccess()) {
                    remoteFiles = ((ListFilesResponse) response).getFilenames();
                }

                // Check the mutable set for the AppIcon
                // If not present, upload the image
                // Check the mutable set for the AppIcon
                // If not present, upload the image
                if (remoteFiles == null || !remoteFiles.contains(SdlService.ICON_FILENAME)) {
                    sendIcon();
                } else {
                    // If the file is already present, send the SetAppIcon request
                    try {
                        proxy.setappicon(ICON_FILENAME, CorrelationIdGenerator.generateId());
                    } catch (SdlException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        this.sendRpcRequest(listFiles);
    }

    /**
     * Sends the app icon through the uploadImage method with correct params
     */
    private void sendIcon() {
        iconCorrelationId = CorrelationIdGenerator.generateId();
        uploadImage(R.drawable.sdl_icon, ICON_FILENAME, iconCorrelationId, true, null);
    }

    /**
     * 发送锁屏的图标
     */
    private void sendLockImg(Bitmap bitmap) {
        lockImgId = CorrelationIdGenerator.generateId();
        uploadImage(0, LOCK_IMG_FILENAME, lockImgId, true, bitmap);
    }

    @Subscribe
    public void onEventMainThread(UploadEvent uploadEvent) {
        if (uploadEvent != null && isLockShow) {
            Bitmap bitmap = uploadEvent.getUploadBm();
            if (bitmap != null) {
                sendLockImg(bitmap);
            }
        }
    }


    @Subscribe
    public void onEventMainThread(StopEvent stopEvent) {
        if (stopEvent != null) {
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    exitSafely();
                }
            }.start();
        }
    }

    /**
     * This method will help upload an image to the head unit
     *
     * @param resource      the R.drawable.__ value of the image you wish to send
     * @param imageName     the filename that will be used to reference this image
     * @param correlationId the correlation id to be used with this request. Helpful for monitoring putfileresponses
     * @param isPersistent  tell the system if the file should stay or be cleared out after connection.
     */
    @SuppressWarnings("SameParameterValue")
    private void uploadImage(int resource, String imageName, int correlationId, boolean isPersistent, Bitmap bitmap) {
        PutFile putFile = new PutFile();
        putFile.setFileType(FileType.GRAPHIC_PNG);
        putFile.setSdlFileName(imageName);
        putFile.setCorrelationID(correlationId);
        putFile.setPersistentFile(isPersistent);
        putFile.setSystemFile(false);
        if (bitmap == null) {
            putFile.setBulkData(contentsOfResource(resource));
        } else {
            putFile.setBulkData(Bitmap2Bytes(bitmap));
        }
        try {
            proxy.sendRPCRequest(putFile);
        } catch (SdlException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param bm
     * @return
     */
    private byte[] Bitmap2Bytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    }

    /**
     * Helper method to take resource files and turn them into byte arrays
     *
     * @param resource Resource file id.
     * @return Resulting byte array.
     */
    private byte[] contentsOfResource(int resource) {
        InputStream is = null;
        try {
            is = getResources().openRawResource(resource);
            ByteArrayOutputStream os = new ByteArrayOutputStream(is.available());
            final int bufferSize = 4096;
            final byte[] buffer = new byte[bufferSize];
            int available;
            while ((available = is.read(buffer)) >= 0) {
                os.write(buffer, 0, available);
            }
            return os.toByteArray();
        } catch (IOException e) {
            Log.w(TAG, "Can't read icon file", e);
            return null;
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * Sends an RPC Request to the connected head unit. Automatically adds a correlation id.
     *
     * @param request the rpc request that is to be sent to the module
     */
    private void sendRpcRequest(RPCRequest request) {
        try {
            proxy.sendRPCRequest(request);
        } catch (SdlException e) {
            e.printStackTrace();
        }
    }

    /**
     * 服务端关闭信号
     *
     * @param info
     * @param e
     * @param reason
     */
    @Override
    public void onProxyClosed(String info, Exception e, SdlDisconnectedReason reason) {
        Log.e(TAG, "onProxyClosed");
        //TODO
        stopSelf();
    }

    @Override
    public void onServiceEnded(OnServiceEnded serviceEnded) {

    }

    @Override
    public void onServiceNACKed(OnServiceNACKed serviceNACKed) {

    }

    @Override
    public void onOnStreamRPC(OnStreamRPC notification) {
        Log.i(TAG, "OnStreamRPC notification from SDL: " + notification);
    }

    @Override
    public void onStreamRPCResponse(StreamRPCResponse response) {
        Log.i(TAG, "StreamRPC response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onError(String info, Exception e) {

    }

    @Override
    public void onGenericResponse(GenericResponse response) {

    }

    @Override
    public void onOnCommand(OnCommand notification) {
        Log.i(TAG, "OnCommand response from SDL: " + notification);
        //TODO
    }

    @Override
    public void onAddCommandResponse(AddCommandResponse response) {
        Log.i(TAG, "AddCommand response from SDL: " + response.getResultCode().name());
    }

    @Override
    public void onAddSubMenuResponse(AddSubMenuResponse response) {
        Log.i(TAG, "AddSubMenu response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onCreateInteractionChoiceSetResponse(CreateInteractionChoiceSetResponse response) {
        Log.i(TAG, "CreateInteractionChoiceSet response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onAlertResponse(AlertResponse response) {
        Log.i(TAG, "Alert response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onDeleteCommandResponse(DeleteCommandResponse response) {
        Log.i(TAG, "DeleteCommand response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onDeleteInteractionChoiceSetResponse(DeleteInteractionChoiceSetResponse response) {
        Log.i(TAG, "DeleteInteractionChoiceSet response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onDeleteSubMenuResponse(DeleteSubMenuResponse response) {
        Log.i(TAG, "DeleteSubMenu response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onPerformInteractionResponse(PerformInteractionResponse response) {
        Log.i(TAG, "PerformInteraction response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onResetGlobalPropertiesResponse(ResetGlobalPropertiesResponse response) {
        Log.i(TAG, "ResetGlobalProperties response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onSetGlobalPropertiesResponse(SetGlobalPropertiesResponse response) {
        Log.i(TAG, "SetGlobalProperties response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onSetMediaClockTimerResponse(SetMediaClockTimerResponse response) {
        Log.i(TAG, "SetMediaClockTimer response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onShowResponse(ShowResponse response) {
        Log.i(TAG, "Show response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onSpeakResponse(SpeakResponse response) {
        Log.i(TAG, "SpeakCommand response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onOnButtonEvent(OnButtonEvent notification) {
        Log.i(TAG, "OnButtonEvent notification from SDL: " + notification);
    }

    @Override
    public void onOnButtonPress(OnButtonPress notification) {
        Log.i(TAG, "OnButtonPress notification from SDL: " + notification);
    }

    @Override
    public void onSubscribeButtonResponse(SubscribeButtonResponse response) {
        Log.i(TAG, "SubscribeButton response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onUnsubscribeButtonResponse(UnsubscribeButtonResponse response) {
        Log.i(TAG, "UnsubscribeButton response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onOnPermissionsChange(OnPermissionsChange notification) {
        Log.i(TAG, "Permision changed: " + notification);
    }

    @Override
    public void onSubscribeVehicleDataResponse(SubscribeVehicleDataResponse response) {
        Log.i(TAG, "UnsubscribeVehicleData response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onUnsubscribeVehicleDataResponse(UnsubscribeVehicleDataResponse response) {

    }

    @Override
    public void onGetVehicleDataResponse(GetVehicleDataResponse response) {
        Log.i(TAG, "GetVehicleData response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onOnVehicleData(OnVehicleData notification) {
        Log.e(TAG, "Vehicle data notification from SDL");
        //TODO Put your vehicle data code here
        //ie, notification.getSpeed().
    }

    @Override
    public void onPerformAudioPassThruResponse(PerformAudioPassThruResponse response) {
        Log.i(TAG, "PerformAudioPassThru response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onEndAudioPassThruResponse(EndAudioPassThruResponse response) {
        Log.i(TAG, "EndAudioPassThru response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onOnAudioPassThru(OnAudioPassThru notification) {
        Log.i(TAG, "OnAudioPassThru notification from SDL: " + notification);
    }

    /**
     * 上传成功之后的回调函数，回调之后把系统图标设置为记录ID的图片
     *
     * @param response
     */
    @Override
    public void onPutFileResponse(PutFileResponse response) {
        Log.e(TAG, "onPutFileResponse from SDL");
        //TODO
        if (response.getCorrelationID() == iconCorrelationId) { //If we have successfully uploaded our icon, we want to set it
            Log.e("icon", "icon");
            try {
                proxy.setappicon(ICON_FILENAME, CorrelationIdGenerator.generateId());//设置封面图片
            } catch (SdlException e) {
                e.printStackTrace();
            }
        } else if (response.getCorrelationID() == lockImgId && isLockShow) {
            Log.e("lock", "lock");
            try {
                Image image = new Image();
                image.setValue(LOCK_IMG_FILENAME);
                image.setImageType(ImageType.DYNAMIC);
                Show show = new Show();
                show.setGraphic(image);
                show.setCorrelationID(lockImgId);
                show.setStatusBar(null);
                show.setOnRPCResponseListener(new OnRPCResponseListener() {
                    @Override
                    public void onResponse(int correlationId, RPCResponse response) {
                        if (((ShowResponse) response).getSuccess()) {
                            Log.i("SdlService", "Successfully showed.");
                        } else {
                            Log.i("SdlService", "Show request was rejected.");
                        }
                    }
                });
                proxy.sendRPCRequest(show);
            } catch (SdlException e) {
                e.printStackTrace();
                Log.e(TAG, "show upload fail");
            }
        }
    }

    @Override
    public void onDeleteFileResponse(DeleteFileResponse response) {
        Log.i(TAG, "DeleteFile response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onListFilesResponse(ListFilesResponse response) {
        Log.i(TAG, "onListFilesResponse from SDL " + response.getResultCode().name());
    }

    @Override
    public void onSetAppIconResponse(SetAppIconResponse response) {
        Log.i(TAG, "SetAppIcon response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onScrollableMessageResponse(ScrollableMessageResponse response) {
        Log.i(TAG, "ScrollableMessage response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onChangeRegistrationResponse(ChangeRegistrationResponse response) {
        Log.i(TAG, "ChangeRegistration response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onSetDisplayLayoutResponse(SetDisplayLayoutResponse response) {
        Log.i(TAG, "SetDisplayLayout response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onOnLanguageChange(OnLanguageChange notification) {
        Log.i(TAG, "OnLanguageChange notification from SDL: " + notification);
    }

    @Override
    public void onOnHashChange(OnHashChange notification) {
        Log.i(TAG, "OnHashChange notification from SDL: " + notification);
    }

    @Override
    public void onSliderResponse(SliderResponse response) {
        Log.i(TAG, "Slider response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onOnDriverDistraction(OnDriverDistraction notification) {
        // Some RPCs (depending on region) cannot be sent when driver distraction is active.
    }

    @Override
    public void onOnTBTClientState(OnTBTClientState notification) {
        Log.i(TAG, "OnTBTClientState notification from SDL: " + notification);
    }

    /**
     * 这里会传来服务器让下载锁屏图标的地址
     *
     * @param notification
     */
    @Override
    public void onOnSystemRequest(OnSystemRequest notification) {
        Log.e(TAG, "OnSystemRequest notification from SDL: " + notification);
        //TODO
    }

    @Override
    public void onSystemRequestResponse(SystemRequestResponse response) {
        Log.i(TAG, "SystemRequest response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onOnKeyboardInput(OnKeyboardInput notification) {
        Log.i(TAG, "OnKeyboardInput notification from SDL: " + notification);
    }

    @Override
    public void onOnTouchEvent(OnTouchEvent notification) {
        Log.i(TAG, "OnTouchEvent notification from SDL: " + notification);
    }

    @Override
    public void onDiagnosticMessageResponse(DiagnosticMessageResponse response) {
        Log.i(TAG, "DiagnosticMessage response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onReadDIDResponse(ReadDIDResponse response) {
        Log.i(TAG, "ReadDID response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onGetDTCsResponse(GetDTCsResponse response) {
        Log.i(TAG, "GetDTCs response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    /**
     * 重载回调提示锁屏状态
     * OFF的时候不需要锁屏
     * 其他的时候进行锁屏操作
     *
     * @param notification
     */
    @Override
    public void onOnLockScreenNotification(OnLockScreenStatus notification) {
        Log.e(TAG, "onOnLockScreenNotification from SDL: " + notification.getShowLockScreen());
        //TODO
    }

    @Override
    public void onDialNumberResponse(DialNumberResponse response) {
        Log.i(TAG, "DialNumber response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onSendLocationResponse(SendLocationResponse response) {
        Log.i(TAG, "SendLocation response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onShowConstantTbtResponse(ShowConstantTbtResponse response) {
        Log.i(TAG, "ShowConstantTbt response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onAlertManeuverResponse(AlertManeuverResponse response) {
        Log.i(TAG, "AlertManeuver response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onUpdateTurnListResponse(UpdateTurnListResponse response) {
        Log.i(TAG, "UpdateTurnList response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onServiceDataACK(int dataSize) {

    }

    @Override
    public void onGetWayPointsResponse(GetWayPointsResponse response) {
        Log.i(TAG, "GetWayPoints response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onSubscribeWayPointsResponse(SubscribeWayPointsResponse response) {
        Log.i(TAG, "SubscribeWayPoints response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onUnsubscribeWayPointsResponse(UnsubscribeWayPointsResponse response) {
        Log.i(TAG, "UnsubscribeWayPoints response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onOnWayPointChange(OnWayPointChange notification) {
        Log.i(TAG, "OnWayPointChange notification from SDL: " + notification);
    }

    @Override
    public void onGetSystemCapabilityResponse(GetSystemCapabilityResponse response) {
        Log.i(TAG, "GetSystemCapabilityResponse from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onGetInteriorVehicleDataResponse(GetInteriorVehicleDataResponse response) {
        Log.i(TAG, "GetInteriorVehicleData response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onButtonPressResponse(ButtonPressResponse response) {
        Log.i(TAG, "ButtonPress response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onSetInteriorVehicleDataResponse(SetInteriorVehicleDataResponse response) {
        Log.i(TAG, "SetInteriorVehicleData response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onOnInteriorVehicleData(OnInteriorVehicleData notification) {
        Log.i(TAG, "OnInteriorVehicleData from SDL: " + notification);
    }

    @Override
    public void onSendHapticDataResponse(SendHapticDataResponse response) {
        Log.i(TAG, "SendHapticData response from SDL: " + response.getResultCode().name() + " Info: " + response.getInfo());
    }

    @Override
    public void onDestroy() {
        exitSafely();
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }

    /**
     * 安全退出&关闭service
     */
    private void exitSafely() {
        //TODO 发送信息关闭锁屏界面
        Log.e(TAG, "safety exit");
        unLockScreen();
        if (proxy != null) {
            try {
                proxy.dispose();
            } catch (SdlException e) {
                e.printStackTrace();
            }
            proxy = null;
        }
    }
}
